Passed
Branch master (7fa550)
by Rafael S.
01:16
created

T_CONST ➔ fixIndex_   B

Complexity

Conditions 5
Paths 2

Size

Total Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 1
rs 8.8571
c 0
b 0
f 0
cc 5
nc 2
nop 2
1
/*
2
 * riff-chunks
3
 * Read and write the chunks of RIFF and RIFX files.
4
 * Copyright (c) 2017-2018 Rafael da Silva Rocha.
5
 * https://github.com/rochars/riff-chunks
6
 *
7
 */
8
9
/** @private */
10
const byteData = require("byte-data");
11
/** @private */
12
const uInt32_ = {"bits": 32};
13
/** @private */
14
const fourCC_ = {"bits": 32, "char": true};
15
16
/**
17
 * Write the bytes of a RIFF/RIFX file.
18
 * @param {!Object} chunks A structure like the return of riffChunks.read().
19
 * @param {boolean} list An optional param indicating if the chunk is LIST.
20
 *      "LIST" chunks should not be rendered as Uint8Array.
21
 * @return {!Array<number>|!Uint8Array} The bytes as Uint8Array when chunkId is
22
 *      "RIFF"/"RIFX" or as Array<number> when chunkId is "LIST".
23
 */
24
function write(chunks, list=false) {
25
    uInt32_["be"] = chunks["chunkId"] == "RIFX";
26
    let bytes = byteData.pack(chunks["chunkId"], fourCC_).concat(
27
        byteData.pack(chunks["chunkSize"], uInt32_),
28
        byteData.pack(chunks["format"], fourCC_),
29
        writeSubChunks_(chunks["subChunks"]));
30
    if (!list) {
31
        bytes = new Uint8Array(bytes);
32
    }
33
    return bytes;
34
}
35
36
/**
37
 * Get the chunks of a RIFF/RIFX file.
38
 * @param {!Uint8Array|!Array<number>} buffer The file bytes.
39
 * @return {!Object} The chunk.
40
 */
41
function read(buffer) {
42
    buffer = [].slice.call(buffer);
43
    let chunkId = getChunkId_(buffer, 0);
44
    uInt32_["be"] = chunkId == "RIFX";
45
    return {
46
        "chunkId": chunkId,
47
        "chunkSize": getChunkSize_(buffer, 0),
48
        "format": byteData.unpack(buffer.slice(8, 12), fourCC_),
49
        "subChunks": getSubChunks_(buffer)
50
    };
51
}
52
53
/**
54
 * Write the sub chunks of a RIFF file.
55
 * @param {!Array<!Object>} chunks The chunks.
56
 * @return {!Array<number>} The chunk bytes.
57
 * @private
58
 */
59
function writeSubChunks_(chunks) {
60
    let subChunks = [];
61
    let i = 0;
62
    while (i < chunks.length) {
63
        if (chunks[i]["chunkId"] == "LIST") {
64
            subChunks = subChunks.concat(write(chunks[i], true));
65
        } else {
66
            subChunks = subChunks.concat(
67
                byteData.pack(chunks[i]["chunkId"], fourCC_),
68
                byteData.pack(chunks[i]["chunkSize"], uInt32_),
69
                chunks[i]["chunkData"]);
70
        }
71
        i++;
72
    }
73
    return subChunks;
74
}
75
76
/**
77
 * Get the sub chunks of a RIFF file.
78
 * @param {!Uint8Array|!Array<number>} buffer the RIFF file bytes.
79
 * @return {!Array<Object>} The subchunks of a RIFF/RIFX or LIST chunk.
80
 * @private
81
 */
82
function getSubChunks_(buffer) {
83
    let chunks = [];
84
    let i = 12;
85
    while(i <= buffer.length - 8) {
86
        chunks.push(getSubChunk_(buffer, i));
87
        i += 8 + chunks[chunks.length - 1]["chunkSize"];
88
        i = i % 2 ? i + 1 : i;
89
    }
90
    return chunks;
91
}
92
93
/**
94
 * Get a sub chunk from a RIFF file.
95
 * @param {!Uint8Array|!Array<number>} buffer the RIFF file bytes.
96
 * @param {number} index The start index of the chunk.
97
 * @return {!Object} A subchunk of a RIFF/RIFX or LIST chunk.
98
 * @private
99
 */
100
function getSubChunk_(buffer, index) {
101
    let chunk = {
102
        "chunkId": getChunkId_(buffer, index),
103
        "chunkSize": getChunkSize_(buffer, index),
104
    };
105
    if (chunk["chunkId"] == "LIST") {
106
        chunk["format"] = byteData.unpack(
107
            buffer.slice(index + 8, index + 12), fourCC_);
108
        chunk["subChunks"] = getSubChunks_(buffer.slice(index));
109
    } else {
110
        let slc = chunk["chunkSize"] % 2 ? chunk["chunkSize"] + 1 : chunk["chunkSize"];
111
        chunk["chunkData"] = buffer.slice(
112
            index + 8, index + 8 + slc);
113
    }
114
    return chunk;
115
}
116
117
/**
118
 * Return the fourCC_ of a chunk.
119
 * @param {!Uint8Array|!Array<number>} buffer the RIFF file bytes.
120
 * @param {number} index The start index of the chunk.
121
 * @return {string} The id of the chunk.
122
 * @private
123
 */
124
function getChunkId_(buffer, index) {
125
    return byteData.unpack(buffer.slice(index, index + 4), fourCC_);
126
}
127
128
/**
129
 * Return the size of a chunk.
130
 * @param {!Uint8Array|!Array<number>} buffer the RIFF file bytes.
131
 * @param {number} index The start index of the chunk.
132
 * @return {number} The size of the chunk without the id and size fields.
133
 * @private
134
 */
135
function getChunkSize_(buffer, index) {
136
    return byteData.unpack(buffer.slice(index + 4, index + 8), uInt32_);
137
}
138
139
module.exports.read = read;
140
module.exports.write = write;
141